package forward.Module.Modules.Move;


import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import forward.api.EventHandler;
import forward.api.Events.Render.EventRender3D;
import forward.api.Events.World.EventMove;
import forward.api.Events.World.EventPreUpdate;
import forward.api.Value.Numbers;
import forward.api.Value.Option;
import forward.Client;
import forward.Manager.ModuleManager;
import forward.Module.Module;
import forward.Module.ModuleType;
import forward.Module.Modules.Combat.Killaura;
import forward.Util.PlayerUtil;
import forward.Util.RenderUtil2;
import net.optifine.MathUtils;
import org.lwjgl.opengl.GL11;

import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;

public class TargetStrafe
        extends Module {
    public Numbers<Double> range = new Numbers("Range", "Range", Double.valueOf(10.0D), Double.valueOf(0.1D), Double.valueOf(10.0D), Double.valueOf(0.1D));

    public Numbers<Double> spaceRange = new Numbers("HightRange", "HightRange", Double.valueOf(5.0D), Double.valueOf(0.1D), Double.valueOf(5.0D), Double.valueOf(0.1D));
    public Entity target;
    private Option onlyInRange = new Option("Only In Range", "Only In Range", false);
    private Option check = new Option("Check", "Check", true);
    private Option<Boolean> auto = new Option("Auto", "Auto", true);
    private Option<Boolean> key = new Option("onJumpKey", "onJumpKey", true);
    private double degree = 0.0D;

    private float groundY;

    private boolean left = true;

    private float rAnims;

    private List<Entity> targets = new ArrayList<>();

    public TargetStrafe() {
        super("TargetStrafe", new String[]{"TargetStrafe"}, ModuleType.Move);
        addValues(this.range, this.spaceRange, this.check, auto, onlyInRange, key);
    }

    public void onEnable() {
        this.targets.clear();
        this.degree = 0.0D;
        this.left = true;
        this.target = null;
        this.rAnims = 0.0F;
    }

    @EventHandler
    public void onRender(EventRender3D event) {
        if (this.target == null)
            return;
        if (this.mc.thePlayer.onGround)
            this.groundY = (float)this.mc.thePlayer.posY;
        int countMod = 0;
        GL11.glPushMatrix();
        GL11.glEnable(3042);
        GL11.glBlendFunc(770, 771);
        GL11.glEnable(2848);
        GL11.glLineWidth(2.0F);
        GL11.glDisable(3553);
        GL11.glEnable(2884);
        GL11.glDisable(2929);
        double renderPosX = (this.mc.getRenderManager()).viewerPosX;
        double renderPosY = (this.mc.getRenderManager()).viewerPosY;
        double renderPosZ = (this.mc.getRenderManager()).viewerPosZ;
        AxisAlignedBB Item = new AxisAlignedBB(-0.175D, 0.0D, -0.175D, 0.175D, 0.35D, 0.175D);
        GL11.glPushMatrix();
        GL11.glTranslated(RenderUtil2.getEntityRenderX(this.target), RenderUtil2.getEntityRenderY(this.target), RenderUtil2.getEntityRenderZ(this.target));
        GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F);
        RenderUtil2.drawCircle((int)Item.minX, (int)Item.minY, ((Double)this.range.getValue()).floatValue(), 1.0F, false, canStrafe() ? (new Color(255, 255, 0)).getRGB() : (new Color(255, 255, 255)).getRGB());
        GL11.glPopMatrix();
        GL11.glColor4f(0.0F, 0.0F, 1.0F, 1.0F);
        GL11.glEnable(2929);
        GL11.glEnable(3553);
        GL11.glDisable(3042);
        GL11.glDisable(2848);
        GL11.glPopMatrix();
    }

    @EventHandler
    private void onUpdate(EventPreUpdate e) {
        if (this.key.getValue()) {
            if(mc.gameSettings.keyBindJump.pressed) {
                if (target != null && ModuleManager.getModuleByClass(Killaura.class).isEnabled() && ModuleManager.getModuleByClass(Speed.class).isEnabled() && auto.getValue()) {
                    mc.gameSettings.keyBindForward.Doing = true;
                }else {
                    mc.gameSettings.keyBindForward.Doing = false;
                }
                Killaura ka = (Killaura)Client.instance.getModuleManager().getModuleByClass(Killaura.class);
                Speed speed = (Speed) Client.instance.getModuleManager().getModuleByClass(Speed.class);

                if (ka.isEnabled()) {
                    this.target = Killaura.curtarget;
                } else {
                    this.target = null;
                }
            }else {
                mc.gameSettings.keyBindForward.Doing = false;
                this.target = null;
            }
        }else {
            if (target != null && ModuleManager.getModuleByClass(Killaura.class).isEnabled() && ModuleManager.getModuleByClass(Speed.class).isEnabled() && auto.getValue()) {
                mc.gameSettings.keyBindForward.Doing = true;
            }else {
                mc.gameSettings.keyBindForward.Doing = false;
            }
            Killaura ka = (Killaura)Client.instance.getModuleManager().getModuleByClass(Killaura.class);
            Speed speed = (Speed)Client.instance.getModuleManager().getModuleByClass(Speed.class);

            if (ka.isEnabled()) {
                this.target = Killaura.curtarget;
            } else {
                this.target = null;
            }
        }
    }
    @EventHandler
    private void onMove(EventMove e) {
        if (canStrafe()) {
            Speed speedM = (Speed)Client.instance.getModuleManager().getModuleByClass(Speed.class);

            double speed = speedM.movementSpeed * 0.99D;
            this.degree = Math.atan2(this.mc.thePlayer.posZ - this.target.posZ, this.mc.thePlayer.posX - this.target.posX);
            this.degree += this.left ? (speed / this.mc.thePlayer.getDistanceXZToEntity(this.target)) : -(speed / this.mc.thePlayer.getDistanceXZToEntity(this.target));
            double x = this.target.posX + ((Double)this.range.getValue()).doubleValue() * Math.cos(this.degree);
            double z = this.target.posZ + ((Double)this.range.getValue()).doubleValue() * Math.sin(this.degree);
            if (((Boolean)this.check.getValue()).booleanValue() && needToChange(x, z)) {
                this.left = !this.left;
                this.degree += 2.0D * (this.left ? (speed / this.mc.thePlayer.getDistanceXZToEntity(this.target)) : -(speed / this.mc.thePlayer.getDistanceXZToEntity(this.target)));
                x = this.target.posX + ((Double)this.range.getValue()).doubleValue() * Math.cos(this.degree);
                z = this.target.posZ + ((Double)this.range.getValue()).doubleValue() * Math.sin(this.degree);
            }
            e.setX(speed * -Math.sin((float)Math.toRadians(MathUtils.toDegree(x, z))));
            e.setZ(speed * Math.cos((float)Math.toRadians(MathUtils.toDegree(x, z))));
        }
    }

    public boolean canStrafe() {
        Killaura ka = (Killaura)Client.instance.getModuleManager().getModuleByClass(Killaura.class);

        Speed speed = (Speed)Client.instance.getModuleManager().getModuleByClass(Speed.class);
        return (this.target != null && PlayerUtil.isMoving() && ka.isEnabled() && speed.isEnabled() && isEnabled() && (!((Boolean)this.onlyInRange.getValue()).booleanValue() || this.target.getDistanceXZToEntity((Entity)this.mc.thePlayer) < ((Double)this.range.getValue()).doubleValue() + ((Double)this.spaceRange.getValue()).doubleValue()));
    }

    public boolean needToChange(double x, double z) {
        if (this.mc.thePlayer.isCollidedHorizontally && this.mc.thePlayer.ticksExisted % 2 == 0)
            return true;
        for (int i = (int)(this.mc.thePlayer.posY + 4.0D); i >= 0; i--) {
            BlockPos playerPos = new BlockPos(x, i, z);
            if (this.mc.theWorld.getBlockState(playerPos).getBlock().equals(Blocks.lava) || this.mc.theWorld.getBlockState(playerPos).getBlock().equals(Blocks.fire))
                return true;
            if (!this.mc.theWorld.isAirBlock(playerPos))
                return false;
        }
        return true;
    }
}

